package com.example.xiaoshuo_yudu.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Component
public class JwtUtils {

    @Value("${xiaoshuo.jwt.key}")
    private String secretKey; // 签名密钥

    @Value("${xiaoshuo.jwt.access-token.expire-time:7200000}") // 默认2小时（毫秒）
    private long accessTokenExpireTime;

    @Value("${xiaoshuo.jwt.refresh-token.expire-time:604800000}") // 默认7天（毫秒）
    private long refreshTokenExpireTime;

    @Autowired
    private StringRedisTemplate redisTemplate;




    /**
     * 解析令牌获取载荷（通用方法）
     * @param token 令牌字符串
     * @return 载荷信息
     * @throws Exception 解析失败（过期、签名错误等）
     */
    public Claims parseToken(String token) throws Exception {
        if (!StringUtils.hasText(token)) {
            throw new IllegalArgumentException("令牌不能为空");
        }
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 将令牌加入黑名单（使其失效）
     * @param headerToken 请求头中的令牌（格式：Bearer <token>）
     * @return 是否成功失效
     */
    public boolean invalidateJwt(String headerToken) {
        if (headerToken == null || !headerToken.startsWith("Bearer ")) {
            return false;
        }
        String token = headerToken.substring(7).trim(); // 提取令牌并去空格
        try {
            Claims claims = parseToken(token);
            String jti = claims.getId(); // 获取令牌唯一标识
            Date expiration = claims.getExpiration(); // 令牌原过期时间

            // 计算剩余有效期（毫秒），确保为正数
            long remainTime = expiration.getTime() - System.currentTimeMillis();
            if (remainTime <= 0) {
                return false; // 已过期的令牌无需加入黑名单
            }

            // 存入Redis黑名单，过期时间设为令牌剩余有效期
            redisTemplate.opsForValue()
                    .set(Const.JWT_BLACK_LIST + jti, "invalid", remainTime, TimeUnit.MILLISECONDS);
            return true;

        } catch (ExpiredJwtException e) {
            // 令牌已过期，无需处理
            return false;
        } catch (Exception e) {
            // 解析失败（无效令牌）
            return false;
        }
    }

    /**
     * 检查令牌是否在黑名单中
     */
    public boolean isTokenBlacklisted(String jti) {
        return redisTemplate.hasKey(Const.JWT_BLACK_LIST + jti);
    }


}